﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Model;
using Ongoal.Quotation.Redis;
using Ongoal.Quotation.Service;
using Ongoal.Quotation.Service.Common;
using Ongoal.Quotation.Service.Interface;
using Ongoal.Quotation.Service.Model;
using Ongoal.Quotation.Service.Param;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation.Service
{
    /// <summary>
    /// 文档相关接口实现
    /// </summary>
    public class DocService : ServiceBase, IDocService
    {
        private static Dictionary<string, IMongoDatabase> bucketDic = new Dictionary<string, IMongoDatabase>();
        private static IRedisProvider? _redis = ServiceProviderContext.ServiceProvider.GetService<IRedisProvider>();
        public DocService()
        {
            if (bucketDic == null || bucketDic.Count == 0)
            {
                List<MongoSetting> mongodbList;
                IMongoClient _client;
                var dbcfgstr = this.Config!["DocSetting"];
                if (!string.IsNullOrEmpty(dbcfgstr))
                    mongodbList = JsonConvert.DeserializeObject<List<MongoSetting>>(dbcfgstr);
                else
                    mongodbList = this.Config!.GetSection("DocSetting").Get<List<MongoSetting>>();

                foreach (var item in mongodbList)
                {
                    _client = new MongoClient(item.ConnectionStr);
                    if (!bucketDic.Keys.Contains(item.DBName))
                        bucketDic.Add(item.DBName, _client.GetDatabase(item.DBName));
                }
            }
        }

        /// <summary>
        /// 获取对应的数据库对象
        /// </summary>
        /// <param name="basename"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private IMongoDatabase GetBase(string basename = "")
        {
            if (bucketDic.ContainsKey(basename))
            {
                return bucketDic[basename];
            }
            else if (bucketDic.Count > 0)
            {
                var defaultkey = bucketDic.Keys.First();
                return bucketDic[defaultkey];
            }
            else
            {
                throw new Exception("无法获取对应的MongoDB数据库");
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public dynamic GetAll(string tableName)
        {
            var db = GetBase();
            var filter = Builders<BsonDocument>.Filter;

            var tempList = db.GetCollection<BsonDocument>(tableName).Find(filter.Empty).ToList().ToJson();
            return BsonSerializer.Deserialize<List<dynamic>>(tempList);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public dynamic Insert(string tableName, BsonDocument obj)
        {
            var db = GetBase();
            obj.Remove("_id");
            db.GetCollection<BsonDocument>(tableName).InsertOne(obj);
            return BsonSerializer.Deserialize<dynamic>(obj.ToJson());
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public dynamic Update(string tableName, BsonDocument obj)
        {
            var temp = new ObjectId(obj.GetValue("_id").ToString());
            var db = GetBase();
            obj.Remove("_id");
            var filter = Builders<BsonDocument>.Filter;
            var result = db.GetCollection<BsonDocument>(tableName).ReplaceOne(filter.Eq("_id", temp), obj);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="idList"></param>
        /// <returns></returns>
        public dynamic Delete(string tableName, List<string> idList)
        {
            //注释部分是因为单节点MongoDB不支持事务操作
            var db = GetBase();
            var filter = new BsonDocument("_id", new BsonDocument("$in", new BsonArray(idList.Select(t => new ObjectId(t)))));
            var result = db.GetCollection<BsonDocument>(tableName).DeleteMany(filter);
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="size"></param>
        /// <param name="index"></param>
        /// <param name="searchJson"></param>
        /// <returns></returns>
        public object Search(string tableName, int size, int index, string searchJson)
        {
            SectionModel section = new SectionModel();
            var db = GetBase();
            var filter = Builders<BsonDocument>.Filter;
            FilterDefinition<BsonDocument> filterDef;
            if (string.IsNullOrEmpty(searchJson))
            {
                filterDef = filter.Empty;
            }
            else
            {
                filterDef = searchJson;
            }
            // = @"{""a"":11,""b"":22,""clist"": { ""$elemMatch"": { ""riqi"": ""2020-10-2""} } }";


            var count = db.GetCollection<BsonDocument>(tableName).Find(filterDef).Count();
            section.Index = index;
            var items = db.GetCollection<BsonDocument>(tableName).Find(filterDef).Skip((index - 1) * size).Limit(size).ToList().ToJson();
            return new
            {
                Count = count,
                Index = index,
                Size = size,
                Items = BsonSerializer.Deserialize<List<dynamic>>(items)
            };
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public dynamic GetOne(string tableName, string id)
        {
            var temp = new ObjectId(id);
            var db = GetBase();
            var filter = Builders<BsonDocument>.Filter;
            var result = db.GetCollection<BsonDocument>(tableName).Find(filter.Eq("_id", temp)).ToList();

            if (result != null && result.Count > 0)
            {
                return BsonSerializer.Deserialize<dynamic>(result[0].ToJson());// result;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 根据查询条件当前单条数据
        /// </summary>
        /// <param name="TableName">数据名</param>
        /// <param name="searchJson">查询条件</param>
        /// <returns></returns>
        public async Task<dynamic> GetOneData(string TableName, string searchJson)
        {
            var db = GetBase();
            var filter = Builders<BsonDocument>.Filter;
            FilterDefinition<BsonDocument> filterDef;
            if (string.IsNullOrEmpty(searchJson))
                filterDef = filter.Empty;
            else
                filterDef = searchJson;
            var result = await db.GetCollection<BsonDocument>(TableName).Find(filterDef).ToListAsync();
            if (result != null && result.Count > 0)
                return BsonSerializer.Deserialize<dynamic>(result[0].ToJson());// result;
            return null;
        }

        /// <summary>
        /// 根据查询条件当前全部数据
        /// </summary>
        /// <param name="TableName">数据名</param>
        /// <param name="searchJson">查询条件</param>
        /// <returns></returns>
        public async Task<dynamic> GetDataList(string TableName, string searchJson)
        {
            var db = GetBase();
            var filter = Builders<BsonDocument>.Filter;
            FilterDefinition<BsonDocument> filterDef;
            if (string.IsNullOrEmpty(searchJson))
                filterDef = filter.Empty;
            else
                filterDef = searchJson;
            var result = await db.GetCollection<BsonDocument>(TableName).Find(filterDef).ToListAsync();
            if (result != null && result.Count > 0)
                return BsonSerializer.Deserialize<dynamic>(result.ToJson());// result;
            return null;
        }
    }
}
